package com.stable.actor.core;

import com.stable.actor.config.ActorSystemConfig;
import com.stable.actor.messages.MessageRouter;
import com.stable.actor.network.NetworkService;
import lombok.extern.slf4j.Slf4j;

import java.util.Map;
import java.util.concurrent.*;
import java.util.List;
import java.util.ArrayList;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * Actor系统 - 管理Actor生命周期
 */
@Slf4j
public class ActorSystem {
    private static ActorSystem defaultInstance;
    private final String name;
    private final Map<String, ActorRef> actors = new ConcurrentHashMap<>();
    private final ScheduledExecutorService scheduler;
    private final ActorSystemConfig config;
    private boolean terminated = false;
    private volatile boolean running = true;

    // 网络服务相关
    private final MessageRouter messageRouter;
    private final NetworkService networkService;
    private final int systemPort;

    // 新增：监控关系存储 - 被监控者路径 -> 监控者路径列表
    private final Map<String, List<String>> watchers = new ConcurrentHashMap<>();

    public ActorSystem(String name) {
        this(name, new ActorSystemConfig());
    }

    public ActorSystem(String name, ActorSystemConfig config) {
        this.name = name;
        this.config = config;
        this.systemPort = config.getSystemPort(); // 系统端口
        this.scheduler = Executors.newScheduledThreadPool(config.getSchedulerThreads());

        // 初始化网络服务 - 整个系统使用一个端口
        this.networkService = new NetworkService(systemPort, this);
        this.messageRouter = new MessageRouter();

        // 启动网络服务
        this.networkService.start();

        startSystemMonitor();
        if (defaultInstance == null) {
            defaultInstance = this;
        }
        log.info("ActorSystem '{}' 初始化完成，端口: {}", name, systemPort);
    }

    /**
     * 获取系统端口
     */
    public int getSystemPort() {
        return systemPort;
    }

    /**
     * 注册监控关系
     */
    public void watch(ActorRef subject, ActorRef watcher) {
        if (subject == null || watcher == null) {
            throw new IllegalArgumentException("Subject and watcher cannot be null");
        }

        String subjectPath = subject.path();
        String watcherPath = watcher.path();

        watchers.computeIfAbsent(subjectPath, k -> new CopyOnWriteArrayList<>())
                .add(watcherPath);

        log.debug("Registered watch: {} -> {}", watcherPath, subjectPath);
    }

    /**
     * 取消监控关系
     */
    public void unwatch(ActorRef subject, ActorRef watcher) {
        if (subject == null || watcher == null) {
            throw new IllegalArgumentException("Subject and watcher cannot be null");
        }

        String subjectPath = subject.path();
        String watcherPath = watcher.path();

        List<String> watcherList = watchers.get(subjectPath);
        if (watcherList != null) {
            watcherList.remove(watcherPath);
            log.debug("Unregistered watch: {} -> {}", watcherPath, subjectPath);
        }
    }

    /**
     * 当 Actor 终止时通知所有监控者
     */
    public void notifyTermination(String terminatedActorPath) {
        List<String> watcherPaths = watchers.remove(terminatedActorPath);
        if (watcherPaths != null && !watcherPaths.isEmpty()) {
            log.info("Notifying {} watchers about termination of {}",
                    watcherPaths.size(), terminatedActorPath);

            for (String watcherPath : watcherPaths) {
                try {
                    ActorRef watcher = findActorByPath(watcherPath);
                    if (watcher != null && watcher.getActor() != null) {
                        // 创建 Terminated 消息
                        ActorRef terminatedActorRef = new ActorRef(terminatedActorPath, null, this, false);
                        Terminated terminatedMsg = new Terminated(terminatedActorRef);

                        // 发送 Terminated 消息给监控者
                        watcher.tell(terminatedMsg, null);
                        log.debug("Notified termination of {} to {}", terminatedActorPath, watcherPath);
                    } else {
                        log.warn("Watcher not found or not available: {}", watcherPath);
                    }
                } catch (Exception e) {
                    log.error("Failed to notify watcher {} about termination of {}",
                            watcherPath, terminatedActorPath, e);
                }
            }
        }
    }

    /**
     * 获取监控指定 Actor 的所有监控者
     */
    public List<ActorRef> getWatchers(String actorPath) {
        List<String> watcherPaths = watchers.get(actorPath);
        if (watcherPaths == null) {
            return new ArrayList<>();
        }

        List<ActorRef> watcherRefs = new ArrayList<>();
        for (String watcherPath : watcherPaths) {
            ActorRef watcher = findActorByPath(watcherPath);
            if (watcher != null) {
                watcherRefs.add(watcher);
            }
        }
        return watcherRefs;
    }

    /**
     * 清理指定 Actor 的所有监控关系
     */
    public void clearWatchers(String actorPath) {
        List<String> removedWatchers = watchers.remove(actorPath);
        if (removedWatchers != null) {
            log.debug("Cleared {} watchers for actor: {}", removedWatchers.size(), actorPath);
        }
    }

    /**
     * 获取默认ActorSystem实例
     */
    public static ActorSystem getDefault() {
        if (defaultInstance == null) {
            throw new IllegalStateException("没有可用的ActorSystem实例，请先创建ActorSystem");
        }
        return defaultInstance;
    }

    /**
     * 创建Actor - 不再需要端口参数
     */
    public ActorRef actorOf(Props props, String name) {
        String path = "/user/" + name;
        StableActor actor = props.createActor();
        ActorRef actorRef = new ActorRef(path, actor, this);
        actor.setSelf(actorRef);
        actor.setSystem(this);

        // 注册到路由表
        registerActor(path, actorRef);
        registerActor(name, actorRef);

        // 启动Actor（不再需要单独的端口）
        actorRef.start();

        log.info("✅ 创建Actor: {} (系统端口: {})", path, systemPort);
        return actorRef;
    }

    /**
     * 创建Actor（兼容旧方法）
     */
    public ActorRef createActor(String path, Class<? extends StableActor> actorClass) {
        try {
            String name = extractNameFromPath(path);

            // 创建Actor实例
            StableActor actorInstance = actorClass.newInstance();

            // 创建ActorRef
            ActorRef actorRef = new ActorRef(path, actorInstance, this);

            // 设置Actor的引用
            setupActorReference(actorInstance, actorRef);

            // 注册到系统
            actors.put(path, actorRef);

            log.info("创建Actor: {} (系统端口: {})", path, systemPort);
            return actorRef;

        } catch (Exception e) {
            log.error("创建Actor失败: {}", path, e);
            return null;
        }
    }

    /**
     * 设置Actor的引用
     */
    private void setupActorReference(StableActor actor, ActorRef actorRef) {
        actor.setSelf(actorRef);
        actor.setSystem(this);
    }

    /**
     * 创建远程Actor引用
     */
    public ActorRef remoteActorOf(String host, int port, String path) {
        RemoteActorRef remoteRef = new RemoteActorRef(host, port, path, this);
        log.info("🔗 创建远程引用: {}@{}:{}", path, host, port);
        return remoteRef;
    }

    /**
     * 发送消息到远程Actor
     */
    public void sendRemoteMessage(String host, int port, String actorPath, Object message, ActorRef sender) {
        try {
            // 通过网络服务发送消息
            networkService.sendMessage(host, port, actorPath, message, sender);
            log.debug("发送远程消息到: {}@{}:{}", actorPath, host, port);
        } catch (Exception e) {
            log.error("发送远程消息失败: {}@{}:{}", actorPath, host, port, e);
            handleDeadLetter(actorPath, message, sender);
        }
    }

    /**
     * 处理接收到的远程消息
     */
    public void receiveRemoteMessage(String sourceHost, int sourcePort, String actorPath, Object message) {
        try {
            ActorRef targetActor = findActorByPath(actorPath);
            if (targetActor != null) {
                // 创建远程发送者引用
                ActorRef remoteSender = new RemoteActorRef(sourceHost, sourcePort, "/remote/sender", this);
                targetActor.tell(message, remoteSender);
                log.debug("接收远程消息: {} <- {}@{}:{}", actorPath, message, sourceHost, sourcePort);
            } else {
                log.warn("远程消息目标Actor不存在: {}", actorPath);
                handleDeadLetter(actorPath, message, null);
            }
        } catch (Exception e) {
            log.error("处理远程消息失败: {}", actorPath, e);
            handleDeadLetter(actorPath, message, null);
        }
    }

    // 查找Actor
    public ActorRef findActor(String name) {
        return actors.get(name);
    }

    // 停止Actor
    public void stop(ActorRef actorRef) {
        if (actorRef.isLocal() && actorRef.path().contains("/user/")) {
            String name = actorRef.path().substring(6); // 移除 "/user/" 前缀
            ActorRef removed = actors.remove(name);
            if (removed != null) {
                // 实际停止逻辑在StableActor中
                log.info("🛑 停止Actor: {}", actorRef);
            }
        }
    }

    // 终止系统
    public void terminate() {
        terminated = true;

        // 停止所有Actor
        for (ActorRef actorRef : actors.values()) {
            if (actorRef.isLocal()) {
                // 调用Actor的stop方法
                actorRef.stop();
            }
        }
        actors.clear();

        // 关闭调度器
        scheduler.shutdown();

        // 关闭网络服务
        if (networkService != null) {
            networkService.shutdown();
        }

        log.info("🛑 ActorSystem终止: {}", name);
    }

    /**
     * 定时任务调度
     */
    public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
                                                  long initialDelay,
                                                  long period,
                                                  TimeUnit unit) {
        return scheduler.scheduleAtFixedRate(command, initialDelay, period, unit);
    }

    // 系统监控
    private void startSystemMonitor() {
        scheduler.scheduleAtFixedRate(() -> {
            if (!terminated) {
                log.info("📊 系统状态 - Actors: {}, 内存: {}MB, 端口: {}",
                        actors.size(),
                        Runtime.getRuntime().totalMemory() / 1024 / 1024,
                        systemPort);
            }
        }, 30, 30, TimeUnit.SECONDS);
    }

    public boolean isTerminated() {
        return terminated;
    }

    /**
     * 路由消息到指定路径的Actor
     */
    public static void routeMessage(String actorPath, Object message) {
        getDefault().internalRouteMessage(actorPath, message);
    }

    /**
     * 路由消息到指定路径的Actor（带发送者）
     */
    public static void routeMessage(String actorPath, Object message, ActorRef sender) {
        getDefault().internalRouteMessage(actorPath, message, sender);
    }

    /**
     * 内部路由实现
     */
    private void internalRouteMessage(String actorPath, Object message) {
        internalRouteMessage(actorPath, message, ActorRef.noSender());
    }

    private void internalRouteMessage(String actorPath, Object message, ActorRef sender) {
        try {
            // 检查是否是远程路径格式 (host:port/path)
            if (actorPath.contains(":")) {
                // 远程消息
                String[] parts = actorPath.split("/", 2);
                String[] hostPort = parts[0].split(":");
                if (hostPort.length == 2) {
                    String host = hostPort[0];
                    int port = Integer.parseInt(hostPort[1]);
                    String remoteActorPath = "/" + (parts.length > 1 ? parts[1] : "");
                    sendRemoteMessage(host, port, remoteActorPath, message, sender);
                    return;
                }
            }

            // 本地消息
            ActorRef targetActor = findActorByPath(actorPath);
            if (targetActor != null) {
                targetActor.tell(message, sender);
                log.debug("路由本地消息: {} -> {}", actorPath, message);
            } else {
                log.warn("路由失败: 未找到Actor - {}", actorPath);
                handleDeadLetter(actorPath, message, sender);
            }
        } catch (Exception e) {
            log.error("路由消息异常: {}", actorPath, e);
            handleDeadLetter(actorPath, message, sender);
        }
    }

    /**
     * 发送消息给Actor
     */
    public void sendMessage(String actorPath, Object message, ActorRef sender) {
        ActorRef target = actors.get(actorPath);
        if (target != null) {
            target.tell(message, sender);
        } else {
            log.warn("Actor不存在: {}", actorPath);
            handleDeadLetter(actorPath, message, sender);
        }
    }

    /**
     * 根据路径查找Actor - 改进版本
     */
    private ActorRef findActorByPath(String actorPath) {
        log.debug("🔍 查找Actor路径: {}", actorPath);

        // 1. 直接查找
        ActorRef actor = actors.get(actorPath);
        if (actor != null) {
            log.debug("✅ 直接找到: {}", actorPath);
            return actor;
        }

        // 2. 如果路径以/user/开头，尝试提取短名称
        if (actorPath.startsWith("/user/")) {
            String shortName = actorPath.substring(6); // 移除 "/user/" 前缀
            actor = actors.get(shortName);
            if (actor != null) {
                log.debug("✅ 通过短名称找到: {}", shortName);
                return actor;
            }
        }

        // 3. 如果是短名称，尝试构建完整路径
        if (!actorPath.startsWith("/")) {
            String fullPath = "/user/" + actorPath;
            actor = actors.get(fullPath);
            if (actor != null) {
                log.debug("✅ 通过完整路径找到: {}", fullPath);
                return actor;
            }
        }

        // 4. 尝试去除开头的斜杠
        if (actorPath.startsWith("/")) {
            String withoutSlash = actorPath.substring(1);
            actor = actors.get(withoutSlash);
            if (actor != null) {
                log.debug("✅ 去除斜杠找到: {}", withoutSlash);
                return actor;
            }
        }

        // 5. 遍历所有键进行包含匹配
        for (String key : actors.keySet()) {
            if (key.contains(actorPath) || actorPath.contains(key)) {
                log.debug("✅ 通过包含匹配找到: {}", key);
                return actors.get(key);
            }
        }

        log.debug("❌ 未找到Actor: {}", actorPath);
        return null;
    }

    /**
     * 解析远程Actor引用
     */
    private ActorRef parseRemoteActorRef(String remotePath) {
        try {
            // 解析格式: "192.168.1.100:8080/user/order"
            String[] parts = remotePath.split("/", 2);
            String[] hostPort = parts[0].split(":");

            if (hostPort.length == 2) {
                String host = hostPort[0];
                int port = Integer.parseInt(hostPort[1]);
                String path = "/" + (parts.length > 1 ? parts[1] : "");

                return new RemoteActorRef(host, port, path, this);
            }
        } catch (Exception e) {
            log.error("❌ 解析远程Actor路径失败: {}", remotePath);
        }
        return null;
    }

    /**
     * 通过子路径查找Actor
     */
    private ActorRef findActorBySubPath(String subPath) {
        for (String path : actors.keySet()) {
            if (path.endsWith(subPath) || path.contains(subPath)) {
                return actors.get(path);
            }
        }
        return null;
    }

    /**
     * 处理死信
     */
    private void handleDeadLetter(String actorPath, Object message, ActorRef sender) {
        log.error("💀 死信: 路径={}, 消息={}, 发送者={}", actorPath, message, sender);
        // 可以在这里记录日志、发送到死信队列等
    }

    /**
     * 注册Actor到路由表（在actorOf方法中调用）
     */
    private void registerActor(String path, ActorRef actorRef) {
        actors.put(path, actorRef);
        log.debug("📝 注册Actor到路由表: {}", path);
    }

    /**
     * 注销Actor
     */
    private void unregisterActor(String path) {
        actors.remove(path);
        log.debug("📝 从路由表注销Actor: {}", path);
    }

    /**
     * 停止Actor
     */
    public void stopActor(String path) {
        ActorRef actorRef = actors.remove(path);
        if (actorRef != null && actorRef.getActor() != null) {
            try {
                // 通知监控者此 Actor 已终止
                notifyTermination(path);

                // 调用 Actor 的停止方法
                actorRef.getActor().onStop();
                log.info("停止Actor: {}", path);
            } catch (Exception e) {
                log.error("停止Actor时发生异常: {}", path, e);
            }
        }

        // 清理监控关系
        clearWatchers(path);
    }

    /**
     * 关闭系统
     */
    public void shutdown() {
        terminated = true;
        running = false;

        // 停止网络服务
        if (networkService != null) {
            networkService.shutdown();
        }

        // 停止所有Actor
        for (String path : actors.keySet()) {
            stopActor(path);
        }

        // 清理所有监控关系
        watchers.clear();

        // 关闭调度器
        if (scheduler != null && !scheduler.isShutdown()) {
            scheduler.shutdown();
            try {
                if (!scheduler.awaitTermination(5, TimeUnit.SECONDS)) {
                    scheduler.shutdownNow();
                }
            } catch (InterruptedException e) {
                scheduler.shutdownNow();
                Thread.currentThread().interrupt();
            }
        }

        // 清理ActorRef静态资源
        ActorRef.shutdown();

        log.info("ActorSystem '{}' 已关闭", name);
    }

    private String extractNameFromPath(String path) {
        int lastSlash = path.lastIndexOf('/');
        return lastSlash >= 0 ? path.substring(lastSlash + 1) : path;
    }

    public String getName() {
        return name;
    }

    public ActorSystemConfig getConfig() {
        return config;
    }



    /**
     * 打印当前所有Actor状态（用于调试）
     */
    public void printActorStatus() {
        log.info("\n📊 ===== Actor系统状态 =====");
        log.info("系统名称: {}", name);
        log.info("系统端口: {}", systemPort);
        log.info("运行状态: {}", (running ? "运行中" : "已停止"));
        log.info("Actor数量: {}", actors.size());

        if (actors.isEmpty()) {
            log.info("❌ 没有注册的Actor");
        } else {
            log.info("📋 注册的Actor列表:");
            for (Map.Entry<String, ActorRef> entry : actors.entrySet()) {
                ActorRef ref = entry.getValue();
                log.info("  🔑 Key: '{}'", entry.getKey());
                log.info("     Path: {}", ref.path());
                log.info("     本地: {}", ref.isLocal());
                log.info("     ---");
            }
        }
        log.info("============================");
    }

    /**
     * 服务端点信息
     */
    private static class ServiceEndpoint {
        private final String host;
        private final int port;

        public ServiceEndpoint(String host, int port) {
            this.host = host;
            this.port = port;
        }

        public String getHost() { return host; }
        public int getPort() { return port; }
    }

    /**
     * 单次延迟执行任务
     */
    public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit) {
        return scheduler.schedule(command, delay, unit);
    }

    /**
     * 单次延迟执行任务（带返回值）
     */
    public <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit) {
        return scheduler.schedule(callable, delay, unit);
    }

    /**
     * 根据名称查找Actor引用（兼容Akka风格的actorFor）
     */
    public ActorRef actorFor(String actorName) {
        return findActorByPath(actorName);
    }

    /**
     * 根据路径查找Actor引用
     */
    public ActorRef actorForPath(String actorPath) {
        return findActorByPath(actorPath);
    }
}
